package com.zoffy.oj_backend.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.gson.Gson;
import com.zoffy.oj_backend.common.ErrorCode;
import com.zoffy.oj_backend.common.IdRequest;
import com.zoffy.oj_backend.exception.BusinessException;
import com.zoffy.oj_backend.model.dto.question.*;
import com.zoffy.oj_backend.model.entity.Question;
import com.zoffy.oj_backend.model.vo.QuestionTinyVo;
import com.zoffy.oj_backend.model.vo.QuestionVo;
import com.zoffy.oj_backend.model.vo.UserVo;
import com.zoffy.oj_backend.service.QuestionService;
import com.zoffy.oj_backend.mapper.QuestionMapper;
import com.zoffy.oj_backend.service.UserService;
import com.zoffy.oj_backend.utils.OSSUtils;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.io.InputStream;
import java.util.List;


/**
 * @author 86170
 * @description 针对表【question(题目表)】的数据库操作Service实现
 * @createDate 2024-02-19 00:29:02
 */
@Service
public class QuestionServiceImpl extends ServiceImpl<QuestionMapper, Question>
        implements QuestionService {

    @Resource
    private OSSUtils ossUtils;

    @Resource
    private UserService userService;
    private final static Gson GSON = new Gson();

    @Override
    public Boolean deleteQuestion(IdRequest idRequest) {
        long id = idRequest.getId();
        this.removeById(id);
        return true;
    }

    @Override
    public Boolean updateQuestion(QuestionUpdateRequest questionUpdateRequest) {
        Question question = new Question();
        BeanUtils.copyProperties(questionUpdateRequest, question);
        List<String> tags = questionUpdateRequest.getTags();
        String judgeConfig = questionUpdateRequest.getJudgeConfig();
        if (tags != null) {
            question.setTags(GSON.toJson(tags));
        }
        if (judgeConfig != null) {
            question.setJudgeConfig(GSON.toJson(judgeConfig));
        }
        this.updateById(question);
        return true;
    }

    @Override
    public Long addQuestion(HttpServletRequest request, QuestionAddRequest questionAddRequest) {
        String title = questionAddRequest.getTitle();
        String content = questionAddRequest.getContent();
        List<String> tags = questionAddRequest.getTags();
        JudgeConfig judgeConfig = questionAddRequest.getJudgeConfig();
        //获取登录信息
        UserVo userVo = userService.currentUserVo(request);
        Long userId = userVo.getId();
        Question question = new Question();
        question.setTitle(title);
        question.setContent(content);
        question.setTags(GSON.toJson(tags));
        question.setJudgeConfig(GSON.toJson(judgeConfig));
        question.setUserId(userId);
        //保存数据
        this.save(question);
//        String fileName="caseFile_"+question.getId();
//        question.setJudgeCase(fileName);
//        this.updateById(question);
//        try{
//            InputStream inputStream = judgeCases.getInputStream();
//            if(!ossUtils.upload(inputStream,fileName)){
//                throw new BusinessException(ErrorCode.SYSTEM_ERROR,"测试用例文件保存失败");
//            }
//        }catch (IOException e){
//            throw new BusinessException(ErrorCode.SYSTEM_ERROR,"测试用例文件保存错误");
//        }
        return question.getId();
    }

    @Override
    public IPage<QuestionVo> listQuestionVoByPage(QuestionQueryRequest questionQueryRequest) {
        int page = questionQueryRequest.getPage();
        int pageSize = questionQueryRequest.getPageSize();
        QueryWrapper<Question> queryWrapper = getQueryWrapper(questionQueryRequest);
        Page<Question> questionPage = this.page(new Page<>(page, pageSize), queryWrapper);
        return questionPage.convert(QuestionVo::obj2Vo);
    }

    @Override
    public IPage<QuestionTinyVo> listQuestionTinyVoByPage(QuestionQueryRequest questionQueryRequest) {
        int page = questionQueryRequest.getPage();
        int pageSize = questionQueryRequest.getPageSize();
        QueryWrapper<Question> queryWrapper = getQueryWrapper(questionQueryRequest);
        Page<Question> questionPage = this.page(new Page<>(page, pageSize), queryWrapper);
        return questionPage.convert(QuestionTinyVo::obj2Vo);
    }

    @Override
    public IPage<QuestionVo> listMyQuestionVoByPage(HttpServletRequest request, QuestionQueryRequest questionQueryRequest) {
        UserVo userVo = userService.currentUserVo(request);
        questionQueryRequest.setUserId(userVo.getId());
        return listQuestionVoByPage(questionQueryRequest);
    }

    @Override
    public QuestionVo getQuestionVoById(long questionId) {
        return QuestionVo.obj2Vo(this.getById(questionId));
    }

    @Override
    public List<JudgeCase> getJudgeCases(String JudgeCaseUrl) {
        InputStream in = ossUtils.getObject(JudgeCaseUrl);
        List<JudgeCase> judgeCases;
        try{
            byte[] bytes = in.readAllBytes();
            judgeCases = JSONUtil.toList(new String(bytes), JudgeCase.class);
        }catch (IOException e){
            throw new BusinessException(ErrorCode.SYSTEM_ERROR,"测试用例读取失败");
        }catch (Exception e){
            throw new BusinessException(ErrorCode.SYSTEM_ERROR,"测试用例反序列化错误");
        }
        return judgeCases;
    }

    @Override
    @Transactional
    public Boolean uploadJudgeCases(HttpServletRequest request,long questionId, MultipartFile file) {
        UserVo userVo = userService.currentUserVo(request);

        QueryWrapper<Question> wrapper=new QueryWrapper<>();
        wrapper.eq("id",questionId);
        wrapper.eq("user_id",userVo.getId());
        Question question = this.getOne(wrapper);
        if(question==null){
            throw new BusinessException(ErrorCode.PARAMS_ERROR,"题目不存在");
        }
        String fileName="caseFile_"+question.getId();
        try{
            InputStream inputStream = file.getInputStream();
            if(!ossUtils.upload(inputStream,fileName)){
                throw new BusinessException(ErrorCode.SYSTEM_ERROR,"测试用例文件保存失败");
            }
        }catch (IOException e){
            throw new BusinessException(ErrorCode.SYSTEM_ERROR,"测试用例文件保存错误");
        }
        question.setJudgeCase(fileName);
        this.updateById(question);
        return true;
    }

    public QueryWrapper<Question> getQueryWrapper(QuestionQueryRequest questionQueryRequest) {
        Long id = questionQueryRequest.getId();
        String title = questionQueryRequest.getTitle();
        String content = questionQueryRequest.getContent();
        List<String> tags = questionQueryRequest.getTags();
        Long userId = questionQueryRequest.getUserId();

        QueryWrapper<Question> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq(ObjectUtils.isNotEmpty(id), "id", id);
        queryWrapper.like(StringUtils.isNotBlank(title), "title", title);
        queryWrapper.like(StringUtils.isNotBlank(content), "content", content);
        if (CollectionUtil.isNotEmpty(tags)) {
            for (String tag : tags) {
                queryWrapper.like("tags", tag);
            }
        }
        queryWrapper.eq(ObjectUtils.isNotEmpty(userId), "user_id", userId);
        return queryWrapper;
    }

}




